home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 227_01 / graf.c < prev    next >
Text File  |  1988-02-07  |  42KB  |  1,502 lines

  1. /*
  2.  * g r a f . c
  3.  * -----------
  4.  * This is the hardware-independant, high-level part of the compatible
  5.  * graphics library.
  6.  *
  7.  * update history
  8.  * --------------
  9.  * May, 27. 1987    Use extended functionality of the hercules low-level
  10.  *                  driver. This driver now allows to write 8 pixel with
  11.  *                  one function call, what dramatically decraeses execution
  12.  *                  time.
  13.  * May, 30. 1987    Same as above for the ega low-level driver.
  14.  *                  Also stack space and execution time needed by paint
  15.  *                  reduced, theirby removing a undocumented function
  16.  *                  (paintfil).
  17.  * May, 31. 1987    Function "polyline" added; begin use of graphics error
  18.  *                  system.
  19.  * Jul, 25. 1987    Begin implemention on reverse-color functions.
  20.  * Aug, 30. 1987    Function fellipsis implemented.
  21.  *            Implemention of reverse-color funtions cancelled,
  22.  *            begin implemention of the more powerful write mode
  23.  *            system (includes reverse colors).
  24.  * Nov, 14. 1987    wrtpixel function added.
  25.  *
  26.  * Written by       Rainer Gerhards
  27.  *                  Petronellastr. 6
  28.  *                  D-5112 Baesweiler
  29.  *                  West Germany
  30.  *                  Phone (49) 2401 - 1601
  31.  */
  32.  
  33. /*
  34.  * Define library implemention mode - forbidden for user!
  35.  */
  36. #define LIB_MODE 2            /* I am the Master module!    */
  37.  
  38. #include <stdio.h>
  39. #include <dos.h>
  40. #include <math.h>
  41. #ifdef     __TURBOC__
  42.   #include <stdlib.h>
  43. #endif
  44.  
  45. #include "graphics.h"
  46.  
  47. #define last3bit(x) ((x) &  0x0007)
  48. #define exclst3b(x) ((x) & ~0x0007)
  49.  
  50. /*
  51.  * global data-items (the user program may access these items) ...
  52.  * are 'til now (Jun, 20. 1987) defined in "graphics.h"!
  53.  */
  54.  
  55. /*
  56.  * The following static items are used by the global/local coordinate system.
  57.  */
  58. static float x_start = 0.0;   /* Beginning x coordinate     */
  59. static float x_step  = 1.0;   /* size of a logical x - unit */
  60. static float y_start = 0.0;   /* Beginning y coordinate     */
  61. static float y_step  = 1.0;   /* size of a logical y - unit */
  62.  
  63. /*
  64.  * function prototypes (if allowed)
  65.  */
  66. #ifdef    USEPROTT
  67. extern void    hline(int, int, int, int);
  68. extern int    paintfil(int, int);
  69. extern int    selcolor(int, int);
  70. extern void    fline(int, int, int, int);
  71. extern void    ffillbox(int, int, int, int);
  72. #endif
  73.  
  74. /*
  75.  *    Auxiliary function set,
  76.  *    the following functions are only called internally from other
  77.  *    functions within this module. This function set duplicates most
  78.  *    of the main function set functions, with the execpetion that
  79.  *    the functions containd in the auxiliary perform their operation
  80.  *    in the non-standard write modes (writemod != WM_NORM).
  81.  *
  82.  *    This improves speed dramatically, but unfortunatly needs a lot
  83.  *    of memory. If anyone think's that the memory requirements are to
  84.  *    big, please contact me. I then will implement an much smaller (but
  85.  *    also much slower) function set. I don't implement it today, because
  86.  *    I see no reason for it. I hope the CP/M programmers will share this
  87.  *    opinion.
  88.  */
  89.  
  90. int    selcolor(x, y)
  91. int    x, y;
  92. /*
  93.  * name        selcolor
  94.  *
  95.  * synopsis    color = selcolor(x, y);
  96.  *        int    x, y;        pixel coordinate
  97.  *
  98.  * description    This function selects the drawing color acording to the
  99.  *        current write mode and the requested color.
  100.  *
  101.  * Note        The requested color must be contained in field curcolor!
  102.  */
  103. {
  104. register int    retcolor;        /* selected color        */
  105.  
  106. retcolor = getpixel(x, y);
  107. switch(writemod)
  108.     {
  109.     case WM_XOR:    retcolor ^= curcolor;
  110.             break;
  111.     case WM_AND:    retcolor &= curcolor;
  112.             break;
  113.     case WM_OR:    retcolor |= curcolor;
  114.             break;
  115.     case WM_INV:    retcolor = ~retcolor;
  116.             break;
  117.     }
  118. return(retcolor);
  119. }
  120.  
  121.  
  122. static void    fline(x1, y1, x2, y2)
  123. int x1, y1;
  124. int x2, y2;
  125. /**
  126. * name          fline
  127. *
  128. * synopsis      line(x1, y1, x2, y2);
  129. *               int x1, y1;            starting coordinate
  130. *               int x2, y2;            ending coordinate
  131. *
  132. * description   This function draws a line of "color" between the
  133. *               starting (x1, y1) and ending (x2, y2) coordinate.
  134. **/
  135. {
  136. register int count;      /* loop counter, highest difference */
  137. register int berr;
  138. int ix, ox, iy, oy;
  139. int zwsp;                /* to swap x2 and y2 */
  140.  
  141. if(y1 == y2)              /* horizontal line? */
  142.   {
  143.   if(x1 > x2)
  144.     {
  145.     zwsp = x1;
  146.     x1 = x2;
  147.     x2 = zwsp;
  148.     }
  149.   for( ; x1 <= x2 ; ++x1)
  150.       setpixel(x1, y1, selcolor(x1, y1));
  151.   }
  152. else if(x1 == x2)          /* vertikal line? */
  153.   {
  154.   if(y1 > y2)
  155.     {
  156.     zwsp = y1;
  157.     y1 = y2;
  158.     y2 = zwsp;
  159.     }
  160.   for( ; y1 <= y2 ; y1++)
  161.       setpixel(x1, y1, selcolor(x1, y1));
  162.   }
  163. else
  164.   {
  165.   if((x2 -= x1) > 0)  /* x difference */
  166.     ix = ox = 1;      /* add in loop */
  167.   else
  168.     {
  169.     ix = ox = -1;     /* subtract in loop */
  170.     x2 = -x2;         /* use absolute difference! */
  171.     }
  172.   if((y2 -= y1) > 0)  /* y difference */
  173.     iy = oy = 1;      /* add in loop */
  174.   else
  175.     {
  176.     iy = oy = -1;     /* subtract in loop */
  177.     y2 = -y2;         /* use absolute difference! */
  178.     }
  179.   if(x2 >= y2)        /* select inner/outer loop to add/subtract */
  180.     {
  181.     zwsp = x2;        /* swap x2, y2 */
  182.     x2 = y2;
  183.     y2 = zwsp;
  184.     ix =              /* modify x-coordinate in outer   */
  185.     oy = 0;           /* and y-coordinate in inner loop */
  186.     }
  187.   else
  188.     iy =              /* modify y-coordinate in outer   */
  189.     ox = 0;           /* and x-coordinate in inner loop */
  190.   berr = (x2 << 1) - y2;
  191.   count = y2 + 1;
  192.   do   /* main loop, draws line */
  193.     {
  194.     setpixel(x1, y1, selcolor(x1, y1));
  195.     if(berr > 0)
  196.       {
  197.       berr += (x2 - y2) << 1;
  198.       x1 += ix;
  199.       y1 += iy;
  200.       }
  201.     else
  202.       berr += x2 << 1;
  203.     x1 += ox;
  204.     y1 += oy;
  205.     }
  206.   while(--count > 0);  /* warning: do ... while! */
  207.   }
  208. }
  209.  
  210.  
  211. static void    ffillbox(x1, y1, x2, y2)
  212. register int x1;
  213. int y1;
  214. int x2, y2;
  215. /**
  216. * name          fillbox
  217. *
  218. * synopsis      fillbox(x1, y1, x2, y2, color);
  219. *               int x1, y1;            upper left corner
  220. *               int x2, y2;            lower right corner
  221. *               int color;             fill color
  222. *
  223. * description   This function fills a given box with the specified color.
  224. *               The box is specified through the upper left (x1, y1) and
  225. *               the lower right (x2, y2) corner.
  226. *               This function is the counterpart to box, which draws the
  227. *               border.
  228. **/
  229. {
  230. int zwsp;                /* to swap coordinates        */
  231. register int yt;            /* temporary y, inner loop    */
  232.  
  233. if(x1 > x2)
  234.   {
  235.   zwsp = x1;
  236.   x1 = x2;
  237.   x2 = zwsp;
  238.   }
  239. if(y1 > y2)
  240.   {
  241.   zwsp = y1;
  242.   y1 = y2;
  243.   y2 = zwsp;
  244.   }
  245. for( ; x1 <= x2 ; ++x1)                /* x loop        */
  246.   for(yt = y1 ; yt <= y2 ; ++yt)        /* y loop        */
  247.     setpixel(x1, yt, selcolor(x1, yt));
  248. }
  249.  
  250.  
  251. static void fcircle(x, y, radius, aspect)
  252. register int x, y;
  253. int radius;
  254. double aspect;
  255. /**
  256. * name          circle
  257. *
  258. * synopsis      circle(x, y, radius, color, aspect)
  259. *               int x, y;              center coordinate
  260. *               int radius;            circle radius
  261. *               double aspect;         aspect ratio
  262. *
  263. * description   This function draws a circle.
  264. **/
  265. {
  266. long asp;                /* use internal long - its faster */
  267. unsigned int invrad;     /* inverse radius - grows form 0 to radius/2 */
  268. int decision;            /* controls decrement of radius */
  269. int tmp;                 /* temporary to modify desicion */
  270. unsigned long offs;      /* compute y-offset */
  271. unsigned int offsi;      /* result y-offset (faster then long!) */
  272. unsigned int round;      /* used to round (y * asp) / 256 */
  273.  
  274. asp = (long) (aspect * 256);   /* using long is much faster! */
  275. invrad = 0;
  276. decision = 3 - (radius << 1);
  277. while(invrad <= radius)
  278.   {
  279.   offs = radius * asp;
  280.   round = ((unsigned int) (offs & 0x00000080)) >> 7;
  281.   offsi = (unsigned int) ((offs >> 8) + round); /* divide by 256 (rounded) */
  282.   setpixel(x + invrad, y + offsi, selcolor(x + invrad, y + offsi));
  283.   setpixel(x + invrad, y - offsi, selcolor(x + invrad, y - offsi));
  284.   setpix